package scan.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import scan.annotation.UsedDataSource;
import scan.route.DynamicDataSource;

import java.lang.reflect.Method;


@Aspect
@Component
public class DataSourceAspect {
    @Autowired
    private PlatformTransactionManager txMangeer;

    @Pointcut("@annotation(scan.annotation.UsedDataSource)")
    public void dataSourcePointCut() {

    }

    /**
     * 以添加了UsedDataSource注解的方法做为切点进行操作
     * @param point
     * @return
     * @throws Throwable
     */
    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        DefaultTransactionDefinition transDefinition = new DefaultTransactionDefinition();
        //设置事务的传播机制
        transDefinition.setPropagationBehavior(DefaultTransactionDefinition.PROPAGATION_REQUIRES_NEW);
        //得到事务。根据事务的传播机制判断是新建事务还是用当前已有的事务
        TransactionStatus transStatus = txMangeer.getTransaction(transDefinition);
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        UsedDataSource ds = method.getAnnotation(UsedDataSource.class);
        /**
         * 忘记注解的情况下默认使用主写库
         */
        if (ds == null) {
            DynamicDataSource.setDataSource("write");
            System.out.println("set datasource is " + "write");
        } else {
            DynamicDataSource.setDataSource(ds.name());
            System.out.println("set datasource is " + ds.name());
        }

        try {
            Object proceed = point.proceed();
            txMangeer.rollback(transStatus);
            return proceed;
        } finally {
            DynamicDataSource.clearDataSource();
        }
    }
}
